﻿
/*!
// A part of "Nana Script Utilities", accept the license at http://nana.codeplex.com/license before use it in your own products.
// 这是《Nana脚本工具箱》的一部分，在您自己的产品中使用以前先接受这个使用许可：http://nana.codeplex.com/license
*/

!function () {
  // Object
  var objProto = Object.prototype;

  if(!Object.getPrototypeOf) {
    Object.getPrototypeOf = function getPrototypeOf(o) {
      return o.constructor.prototype;
    };
  }

  if(!Object.getOwnPropertyDescriptor) {
    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(o, p) {
      /*
      1. If Type(O) is not Object throw a TypeError exception.
      2. Let name be ToString(P).
      3. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument name.
      4. Return the result of calling FromPropertyDescriptor(desc) (8.10.4).
      */
    }
  }

  if(!Object.getOwnPropertyNames) {
    Object.getOwnPropertyNames = function getOwnPropertyNames(o) {
      var arr = [];
      if(o.constructor != String) {
        for(var n in o) {
          if(o.hasOwnProperty(n))
            arr.push(n);
        }
        return arr;
      } else {
        var len = o.length;
        for(var i = 0; i < len; i++) {
          arr[i] = i;
        }
        return arr;
      }
    }
  }

  if(!Object.create) {
    Object.create = function create(o, p) {
      function c() { };
      c.prototype = o;
      var r = new c;
      if(p) {
        defineProperties(r, p);
      }
      return r;
    }
  }

  if(!Object.defineProperty) {
    Object.defineProperty = function defineProperty(o, p, a) {
      /*
      1.If Type(O) is not Object throw a TypeError exception.
      2.Let name be ToString(P).
      3.Let desc be the result of calling ToPropertyDescriptor with Attributes as the argument.
      4.Call the [[DefineOwnProperty]] internal method of O with arguments name, desc, and true.
      5.Return O.
      */
    }
  }

  function defineProperties(o, p) {
    for(var n in p) {
      if(p.propertyIsEnumerable(n)) {
        o[n] = p[n];
      }
    }
  }
  if(!Object.defineProperties) {
    Object.defineProperties = defineProperties;
  }

  if(!Object.keys) {
    Object.keys = function keys(o) {
      var arr = [];
      for(var n in o) {
        if(o.propertyIsEnumerable(n))
          arr.push(n);
      }
      return arr;
    }
  }

  
  /*
  8.12 Algorithms for Object Internal Methods
  In the following algorithm descriptions, assume O is a native ECMAScript object, P is a String, Desc is a Property Description record, and Throw is a Boolean flag.

  8.12.1 [[GetOwnProperty]] (P)
  When the [[GetOwnProperty]] internal method of O is called with property name P, the following steps are taken:
  1.  If O doesn’t have an own property with name P, return undefined.
  2.  Let D be a newly created Property Descriptor with no fields.
  3.  Let X be O’s own property named P.
  4.  If X is a data property, then
  a.  Set D.[[Value]] to the value of X’s [[Value]] attribute.
  b.  Set D.[[Writable]] to the value of X’s [[Writable]] attribute
  5.  Else X is an accessor property, so
  a.  Set D.[[Get]] to the value of X’s [[Get]] attribute.
  b.  Set D.[[Set]] to the value of X’s [[Set]] attribute.
  6.  Set D.[[Enumerable]] to the value of X’s [[Enumerable]] attribute.
  7.  Set D.[[Configurable]] to the value of X’s [[Configurable]] attribute.
  8.  Return D.
  However, if O is a String object it has a more elaborate [[GetOwnProperty]] internal method defined in 15.5.5.2.
  
  8.12.2 [[GetProperty]] (P)
  When the [[GetProperty]] internal method of O is called with property name P, the following steps are taken:
  1.  Let prop be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
  2.  If prop is not undefined, return prop.
  3.  Let proto be the value of the [[Prototype]] internal property of O.
  4.  If proto is null, return undefined.
  5.  Return the result of calling the [[GetProperty]] internal method of proto with argument P.
  
  8.12.3 [[Get]] (P)
  When the [[Get]] internal method of O is called with property name P, the following steps are taken:
  8.  Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
  9.  If desc is undefined, return undefined.
  10.  If IsDataDescriptor(desc) is true, return desc.[[Value]].
  11.  Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].
  12.  If getter is undefined, return undefined.
  13.  Return the result calling the [[Call]] internal method of getter providing O as the this value and providing no arguments.
  
  8.12.4 [[CanPut]] (P)
  When the [[CanPut]] internal method of O is called with property name P, the following steps are taken:
  1.  Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.
  2.  If desc is not undefined, then
  a.  If IsAccessorDescriptor(desc) is true, then
  i.  If desc.[[Set]] is undefined, then return false.
  ii.  Else return true.
  b.  Else, desc must be a DataDescriptor so return the value of desc.[[Writable]].
  3.  Let proto be the [[Prototype]] internal property of O.
  4.  If proto is null, then return the value of the [[Extensible]] internal property of O.
  5.  Let inherited be the result of calling the [[GetProperty]] internal method of proto with property name P.
  6.  If inherited is undefined, return the value of the [[Extensible]] internal property of O.
  7.  If IsAccessorDescriptor(inherited) is true, then
  a.  If inherited.[[Set]] is undefined, then return false.
  b.  Else return true.
  8.  Else, inherited must be a DataDescriptor
  a.  If the [[Extensible]] internal property of O is false, return false.
  b.  Else return the value of inherited.[[Writable]].
  Host objects may define additional constraints upon [[Put]] operations. If possible, host objects should not allow [[Put]] operations in situations where this definition of [[CanPut]] returns false.
  
  8.12.5 [[Put]] ( P, V, Throw )
  When the [[Put]] internal method of O is called with property P, value V, and Boolean flag Throw, the following steps are taken:
  1.  If the result of calling the [[CanPut]] internal method of O with argument P is false, then
  a.  If Throw is true, then throw a TypeError exception.
  b.  Else return.
  2.  Let ownDesc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.
  3.  If IsDataDescriptor(ownDesc) is true, then
  a.  Let valueDesc be the Property Descriptor {[[Value]]: V}.
  b.  Call the [[DefineOwnProperty]] internal method of O passing P, valueDesc, and Throw as arguments.
  c.  Return.
  4.  Let desc be the result of calling the [[GetProperty]] internal method of O with argument P. This may be either an own or inherited accessor property descriptor or an inherited data property descriptor.
  5.  If IsAccessorDescriptor(desc) is true, then
  a.  Let setter be desc.[[Set]] which cannot be undefined.
  b.  Call the [[Call]] internal method of setter providing O as the this value and providing V as the sole argument.
  6.  Else, create a named data property named P on object O as follows
  a.  Let newDesc be the Property Descriptor {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.
  b.  Call the [[DefineOwnProperty]] internal method of O passing P, newDesc, and Throw as arguments.
  7.  Return.
  
  8.12.6 [[HasProperty]] (P)
  When the [[HasProperty]] internal method of O is called with property name P, the following steps are taken:
  1.  Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
  2.  If desc is undefined, then return false.
  3.  Else return true.
  
  8.12.7 [[Delete]] (P, Throw)
  When the [[Delete]] internal method of O is called with property name P and the Boolean flag Throw, the following steps are taken:
  1.  Let desc be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
  2.  If desc is undefined, then return true.
  3.  If desc.[[Configurable]] is true, then
  a.  Remove the own property with name P from O.
  b.  Return true.
  4.  Else if Throw, then throw a TypeError exception.
  5.  Return false.
  
  8.12.8 [[DefaultValue]] (hint)
  When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
  1.  Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
  2.  If IsCallable(toString) is true then,
  a.  Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
  b.  If str is a primitive value, return str.
  3.  Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".
  4.  If IsCallable(valueOf) is true then,
  a.  Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
  b.  If val is a primitive value, return val.
  5.  Throw a TypeError exception.
  When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:
  1.  Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".
  2.  If IsCallable(valueOf) is true then,
  a.  Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
  b.  If val is a primitive value, return val.
  3.  Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
  4.  If IsCallable(toString) is true then,
  a.  Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
  b.  If str is a primitive value, return str.
  5.  Throw a TypeError exception.
  When the [[DefaultValue]] internal method of O is called with no hint, then it behaves as if the hint were Number, unless O is a Date object (see 15.9.6), in which case it behaves as if the hint were String.
  The above specification of [[DefaultValue]] for native objects can return only primitive values. If a host object implements its own [[DefaultValue]] internal method, it must ensure that its [[DefaultValue]] internal method can return only primitive values.
  
  8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)
  In the following algorithm, the term “Reject” means “If Throw is true, then throw a TypeError exception, otherwise return false”. The algorithm contains steps that test various fields of the Property Descriptor Desc for specific values. The fields that are tested in this manner need not actually exist in Desc. If a field is absent then its value is considered to be false.
  When the [[DefineOwnProperty]] internal method of O is called with property name P, property descriptor Desc, and Boolean flag Throw, the following steps are taken:
  1.  Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
  2.  Let extensible be the value of the [[Extensible]] internal property of O.
  3.  If current is undefined and extensible is false, then Reject.
  4.  If current is undefined and extensible is true, then
  a.  If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then
  i.  Create an own data property named P of object O whose [[Value]], [[Writable]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value. © Ecma International 2009 41
  b.  Else, Desc must be an accessor Property Descriptor so,
  i.  Create an own accessor property named P of object O whose [[Get]], [[Set]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value.
  c.  Return true.
  5.  Return true, if every field in Desc is absent.
  6.  Return true, if every field in Desc also occurs in current and the value of every field in Desc is the same value as the corresponding field in current when compared using the SameValue algorithm (9.12).
  7.  If the [[Configurable]] field of current is false then
  a.  Reject, if the [[Configurable]] field of Desc is true.
  b.  Reject, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.
  8.  If IsGenericDescriptor(Desc) is true, then no further validation is required.
  9.  Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then
  a.  Reject, if the [[Configurable]] field of current is false.
  b.  If IsDataDescriptor(current) is true, then
  i.  Convert the property named P of object O from a data property to an accessor property. Preserve the existing values of the converted property’s [[Configurable]] and [[Enumerable]] attributes and set the rest of the property’s attributes to their default values.
  c.  Else,
  i.  Convert the property named P of object O from an accessor property to a data property. Preserve the existing values of the converted property’s [[Configurable]] and [[Enumerable]] attributes and set the rest of the property’s attributes to their default values.
  10.  Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
  a.  If the [[Configurable]] field of current is false, then
  i.  Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true.
  ii.  If the [[Writable]] field of current is false, then
  1.  Reject, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false.
  b.  else, the [[Configurable]] field of current is true, so any change is acceptable.
  11.  Else, IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true so,
  a.  If the [[Configurable]] field of current is false, then
  i.  Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.
  ii.  Reject, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false.
  12.  For each attribute field of Desc that is present, set the correspondingly named attribute of the property named P of object O to the value of the field.
  13.  Return true.
  However, if O is an Array object, it has a more elaborate [[DefineOwnProperty]] internal method defined in 15.4.5.1.
  NOTE Step 10.b allows any field of Desc to be different from the corresponding field of current if current’s [[Configurable]] field is true. This even permits changing the [[Value]] of a property whose [[Writable]] attribute is false. This is allowed because a true [[Configurable]] attribute would permit an equivalent sequence of calls where [[Writable]] is first set to true, a new [[Value]] is set, and then [[Writable]] is set to false.
  */
}
!function () {
  // Array
  var arrProto = Array.prototype;
}
!function () {
  // String
  var strProto = String.prototype;
}
!function () {
  // Number
  var NumProto = Number.prototype;
}
!function () {
  // Boolean
  var boolProto = Boolean.prototype;
}
!function () {
  // Date
  var dateProto = Date.prototype;
}
!function () {
  // RegExp
  var rxProto = RegExp.prototype;
}
!function () {
  // Error
  var errProto = Error.prototype;
}
!function () {
  // Function
  var funcProto = Function.prototype;
} ();
